package com.gitee.wsl.transform.validator.func

import arrow.core.Either
import arrow.core.Tuple4
import arrow.core.Tuple5
import arrow.core.Tuple6
import arrow.core.Tuple7
import arrow.core.Tuple8
import arrow.core.Tuple9
import com.gitee.wsl.base.Tuple10
import com.gitee.wsl.transform.validator.ValidatorWithTransform

fun <INPUT, A, B, ERROR> ValidatorWithTransform.Companion.zip(
    p1: ValidatorWithTransform<INPUT, A, ERROR>,
    p2: ValidatorWithTransform<INPUT, B, ERROR>,
): ValidatorWithTransform<INPUT, Pair<A, B>, ERROR> = ValidatorWithTransform { input ->
   Either.zipOrAccumulate(p1.validate(input), p2.validate(input)) { a, b -> Pair(a, b) }
}

fun <INPUT, A, B, C, ERROR> ValidatorWithTransform.Companion.zip(
    p1: ValidatorWithTransform<INPUT, A, ERROR>,
    p2: ValidatorWithTransform<INPUT, B, ERROR>,
    p3: ValidatorWithTransform<INPUT, C, ERROR>,
): ValidatorWithTransform<INPUT, Triple<A, B, C>, ERROR> = ValidatorWithTransform { input ->
   Either.zipOrAccumulate(p1.validate(input), p2.validate(input), p3.validate(input)) { a, b, c -> Triple(a, b, c) }
}

fun <INPUT, A, B, C, D, ERROR> ValidatorWithTransform.Companion.zip(
    p1: ValidatorWithTransform<INPUT, A, ERROR>,
    p2: ValidatorWithTransform<INPUT, B, ERROR>,
    p3: ValidatorWithTransform<INPUT, C, ERROR>,
    p4: ValidatorWithTransform<INPUT, D, ERROR>,
): ValidatorWithTransform<INPUT, Tuple4<A, B, C, D>, ERROR> = ValidatorWithTransform { input ->
   Either.zipOrAccumulate(
      p1.validate(input),
      p2.validate(input),
      p3.validate(input),
      p4.validate(input),
   ) { a, b, c, d ->
      Tuple4(a, b, c, d)
   }
}

fun <INPUT, A, B, C, D, E, ERROR> ValidatorWithTransform.Companion.zip(
    p1: ValidatorWithTransform<INPUT, A, ERROR>,
    p2: ValidatorWithTransform<INPUT, B, ERROR>,
    p3: ValidatorWithTransform<INPUT, C, ERROR>,
    p4: ValidatorWithTransform<INPUT, D, ERROR>,
    p5: ValidatorWithTransform<INPUT, E, ERROR>,
): ValidatorWithTransform<INPUT, Tuple5<A, B, C, D, E>, ERROR> = ValidatorWithTransform { input ->
   Either.zipOrAccumulate(
      p1.validate(input),
      p2.validate(input),
      p3.validate(input),
      p4.validate(input),
      p5.validate(input),
   ) { a, b, c, d, e ->
      Tuple5(a, b, c, d, e)
   }
}

fun <INPUT, A, B, C, D, E, F, ERROR> ValidatorWithTransform.Companion.zip(
    p1: ValidatorWithTransform<INPUT, A, ERROR>,
    p2: ValidatorWithTransform<INPUT, B, ERROR>,
    p3: ValidatorWithTransform<INPUT, C, ERROR>,
    p4: ValidatorWithTransform<INPUT, D, ERROR>,
    p5: ValidatorWithTransform<INPUT, E, ERROR>,
    p6: ValidatorWithTransform<INPUT, F, ERROR>,
): ValidatorWithTransform<INPUT, Tuple6<A, B, C, D, E, F>, ERROR> = ValidatorWithTransform { input ->
   Either.zipOrAccumulate(
      p1.validate(input),
      p2.validate(input),
      p3.validate(input),
      p4.validate(input),
      p5.validate(input),
      p6.validate(input),
   ) { a, b, c, d, e, f ->
      Tuple6(a, b, c, d, e, f)
   }
}

fun <INPUT, A, B, C, D, E, F, G, ERROR> ValidatorWithTransform.Companion.zip(
    p1: ValidatorWithTransform<INPUT, A, ERROR>,
    p2: ValidatorWithTransform<INPUT, B, ERROR>,
    p3: ValidatorWithTransform<INPUT, C, ERROR>,
    p4: ValidatorWithTransform<INPUT, D, ERROR>,
    p5: ValidatorWithTransform<INPUT, E, ERROR>,
    p6: ValidatorWithTransform<INPUT, F, ERROR>,
    p7: ValidatorWithTransform<INPUT, G, ERROR>,
): ValidatorWithTransform<INPUT, Tuple7<A, B, C, D, E, F, G>, ERROR> = ValidatorWithTransform { input ->
   Either.zipOrAccumulate(
      p1.validate(input),
      p2.validate(input),
      p3.validate(input),
      p4.validate(input),
      p5.validate(input),
      p6.validate(input),
      p7.validate(input),
   ) { a, b, c, d, e, f, g ->
      Tuple7(a, b, c, d, e, f, g)
   }
}

fun <INPUT, A, B, C, D, E, F, G, H, ERROR> ValidatorWithTransform.Companion.zip(
    p1: ValidatorWithTransform<INPUT, A, ERROR>,
    p2: ValidatorWithTransform<INPUT, B, ERROR>,
    p3: ValidatorWithTransform<INPUT, C, ERROR>,
    p4: ValidatorWithTransform<INPUT, D, ERROR>,
    p5: ValidatorWithTransform<INPUT, E, ERROR>,
    p6: ValidatorWithTransform<INPUT, F, ERROR>,
    p7: ValidatorWithTransform<INPUT, G, ERROR>,
    p8: ValidatorWithTransform<INPUT, H, ERROR>,
): ValidatorWithTransform<INPUT, Tuple8<A, B, C, D, E, F, G, H>, ERROR> = ValidatorWithTransform { input ->
   Either.zipOrAccumulate(
      p1.validate(input),
      p2.validate(input),
      p3.validate(input),
      p4.validate(input),
      p5.validate(input),
      p6.validate(input),
      p7.validate(input),
      p8.validate(input),
   ) { a, b, c, d, e, f, g, h ->
      Tuple8(a, b, c, d, e, f, g, h)
   }
}

fun <INPUT, A, B, C, D, E, F, G, H, I, ERROR> ValidatorWithTransform.Companion.zip(
    p1: ValidatorWithTransform<INPUT, A, ERROR>,
    p2: ValidatorWithTransform<INPUT, B, ERROR>,
    p3: ValidatorWithTransform<INPUT, C, ERROR>,
    p4: ValidatorWithTransform<INPUT, D, ERROR>,
    p5: ValidatorWithTransform<INPUT, E, ERROR>,
    p6: ValidatorWithTransform<INPUT, F, ERROR>,
    p7: ValidatorWithTransform<INPUT, G, ERROR>,
    p8: ValidatorWithTransform<INPUT, H, ERROR>,
    p9: ValidatorWithTransform<INPUT, I, ERROR>,
): ValidatorWithTransform<INPUT, Tuple9<A, B, C, D, E, F, G, H, I>, ERROR> = ValidatorWithTransform { input ->
   Either.zipOrAccumulate(
      p1.validate(input),
      p2.validate(input),
      p3.validate(input),
      p4.validate(input),
      p5.validate(input),
      p6.validate(input),
      p7.validate(input),
      p8.validate(input),
      p9.validate(input),
   ) { a, b, c, d, e, f, g, h, i ->
      Tuple9(a, b, c, d, e, f, g, h, i)
   }
}

fun <INPUT, A, B, C, D, E, F, G, H, I, J, ERROR> ValidatorWithTransform.Companion.zip(
    p1: ValidatorWithTransform<INPUT, A, ERROR>,
    p2: ValidatorWithTransform<INPUT, B, ERROR>,
    p3: ValidatorWithTransform<INPUT, C, ERROR>,
    p4: ValidatorWithTransform<INPUT, D, ERROR>,
    p5: ValidatorWithTransform<INPUT, E, ERROR>,
    p6: ValidatorWithTransform<INPUT, F, ERROR>,
    p7: ValidatorWithTransform<INPUT, G, ERROR>,
    p8: ValidatorWithTransform<INPUT, H, ERROR>,
    p9: ValidatorWithTransform<INPUT, I, ERROR>,
    p10: ValidatorWithTransform<INPUT, J, ERROR>,
): ValidatorWithTransform<INPUT, Tuple10<A, B, C, D, E, F, G, H, I, J>, ERROR> = ValidatorWithTransform { input ->
   Either.zipOrAccumulate(
      p1.validate(input),
      p2.validate(input),
      p3.validate(input),
      p4.validate(input),
      p5.validate(input),
      p6.validate(input),
      p7.validate(input),
      p8.validate(input),
      p9.validate(input),
      p10.validate(input),
   ) { a, b, c, d, e, f, g, h, i, j ->
      Tuple10(a, b, c, d, e, f, g, h, i, j)
   }
}
